package com.fruit.service.fruit;

import com.fruit.bean.constant.factory.PageFactory;
import com.fruit.bean.dto.fruit.FruitStockInfoDto;
import com.fruit.bean.dto.fruit.FruitStockOrderInfoDto;
import com.fruit.bean.entity.fruit.FruitStockInfo;
import com.fruit.bean.entity.fruit.FruitStockOrderInfo;
import com.fruit.bean.entity.fruit.FruitTypeInfo;
import com.fruit.bean.entity.system.User;
import com.fruit.bean.enumeration.fruit.FruitStockOutStatusEnum;
import com.fruit.bean.enumeration.fruit.FruitStockStatusEnum;
import com.fruit.bean.vo.front.Rets;
import com.fruit.bean.vo.query.DynamicSpecifications;
import com.fruit.bean.vo.query.SearchFilter;
import com.fruit.dao.fruit.FruitStockOrderRepository;
import com.fruit.dao.fruit.FruitStockRepository;
import com.fruit.dao.fruit.FruitTypeRepository;
import com.fruit.dao.system.UserRepository;
import com.fruit.service.BaseService;
import com.fruit.utils.BigDecimalUtils;
import com.fruit.utils.factory.Page;
import org.hibernate.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
public class FruitStockOrderService extends BaseService<FruitStockOrderInfo,Long, FruitStockOrderRepository> {

    @Autowired
    private FruitStockOrderRepository fruitStockOrderRepository;

    @Autowired
    private FruitStockRepository fruitStockRepository;

    @Autowired
    private FruitTypeRepository typeRepository;

    @Autowired
    private UserRepository userRepository;

    public Object inOutStockOrder(FruitStockOrderInfoDto stockOrderInfoDto){
        FruitStockOrderInfo fruitStockOrderInfo = new FruitStockOrderInfo();
        fruitStockOrderInfo.setStockOrderTime(new Date());
        fruitStockOrderInfo.setStockOrderNumber(stockOrderInfoDto.getStockOrderNumber());
        fruitStockOrderInfo.setStockInOut(stockOrderInfoDto.getStokcInOut());
        List<FruitTypeInfo> fruitTypeInfoList = typeRepository.findAll();
        fruitStockOrderInfo.setUserId(stockOrderInfoDto.getUserId());

        // 判断水果类型是否存在
        for(FruitTypeInfo typeInfo : fruitTypeInfoList){
            if(typeInfo.getFruitTypeName().equals(stockOrderInfoDto.getFruitType())){
                fruitStockOrderInfo.setFruitTypeId(typeInfo.getFruitTypeId());
                break;
            }
        }
        //查询是否存在库存信息(根据用户及其入库的水果类型来查找是否有对应库存)
        FruitStockInfo fruitStockInfo = fruitStockRepository.findFruitStockInfoByFruitTypeIdAndAndUserId(
                fruitStockOrderInfo.getFruitTypeId(),fruitStockOrderInfo.getUserId());
        if(stockOrderInfoDto.getStokcInOut() == 1){
            // 出库
            if (null == fruitStockInfo) {
                //没有库存，新增库存信息
                return Rets.failure("没有找到对应的库存信息");
            }

            if(fruitStockInfo.getFruitStockNumber() < stockOrderInfoDto.getStockOrderNumber()){
                //库存不足
                return Rets.failure("库存不足，无法出库");
            }
        }
        if(null == fruitStockOrderInfo.getFruitTypeId()){
            // 水果类型不存在，则新增
            FruitTypeInfo fruitTypeInfo = new FruitTypeInfo();
            fruitTypeInfo.setFruitTypeName(stockOrderInfoDto.getFruitType());
            FruitTypeInfo saveRes = typeRepository.save(fruitTypeInfo);
            fruitStockOrderInfo.setFruitTypeId(saveRes.getFruitTypeId());
        }
        //初始化订单状态
        fruitStockOrderInfo.setStockOrderStatus(FruitStockOutStatusEnum.WAIT_ACCEPT.getCode());
        fruitStockOrderRepository.save(fruitStockOrderInfo);

        if(stockOrderInfoDto.getStokcInOut() == 0) {
            // 入库
            fruitStockInfo = new FruitStockInfo();
            fruitStockInfo.setUserId(fruitStockOrderInfo.getUserId());
            fruitStockInfo.setFruitStockNumber(fruitStockOrderInfo.getStockOrderNumber());
            fruitStockInfo.setFruitTypeId(fruitStockOrderInfo.getFruitTypeId());
            fruitStockInfo.setFruitStockDeficit(100D);
            fruitStockInfo.setFruitStockStatus(FruitStockStatusEnum.WAIT_ACCEPT.getCode());
            fruitStockInfo.setFruitStockInitNumber(fruitStockInfo.getFruitStockNumber());
            fruitStockRepository.save(fruitStockInfo);
        }else{
            if(fruitStockInfo.getFruitStockNumber() >= stockOrderInfoDto.getStockOrderNumber()){
                fruitStockRepository.save(fruitStockInfo);
            }
        }
        return Rets.success();
    }

    public List<FruitStockOrderInfoDto> listStockOrder(){
        List<FruitStockOrderInfo> fruitStockOrderInfoList = this.queryAll();
        List<FruitStockOrderInfoDto> fruitStockOrderInfoDtoList = new ArrayList<>();
        for(FruitStockOrderInfo fruitStockOrderInfo : fruitStockOrderInfoList){
            FruitStockOrderInfoDto fruitStockOrderInfoDto = new FruitStockOrderInfoDto();
            String fruitTypeName = typeRepository.getOne(fruitStockOrderInfo.getFruitTypeId()).getFruitTypeName();
            Optional<User> user = userRepository.findById(fruitStockOrderInfo.getUserId());
            fruitStockOrderInfoDto.setUserName(user.get().getAccount());
            fruitStockOrderInfoDto.setStockOrderNumber(fruitStockOrderInfo.getStockOrderNumber());
            fruitStockOrderInfoDto.setStokcInOutStr(
                    fruitStockOrderInfo.getStockInOut() == 1?"出库":"入库");
            fruitStockOrderInfoDto.setFruitType(fruitTypeName + "-"+fruitStockOrderInfoDto.getStokcInOutStr());
            fruitStockOrderInfoDto.setStockInOutTime(fruitStockOrderInfo.getStockOrderTime());
            fruitStockOrderInfoDtoList.add(fruitStockOrderInfoDto);
        }
        return fruitStockOrderInfoDtoList;
    }

    public Page<FruitStockInfoDto> queryStockOutPage() {
        Page<FruitStockInfo> page = new PageFactory().defaultPage();
        Page<FruitStockInfoDto> pageRes = new PageFactory().defaultPage();
        Pageable pageable;
        if (page.getSort() != null) {
            pageable = PageRequest.of(page.getCurrent() - 1, page.getSize(), page.getSort());
        } else {
            pageable = PageRequest.of(page.getCurrent() - 1, page.getSize(), Sort.Direction.DESC, "id");
        }
        if(page.getFilters() != null){
            page.getFilters().add(new SearchFilter("stockInOut", SearchFilter.Operator.EQ,1));
        }else{
            List<SearchFilter> filters = new ArrayList<>();
            filters.add(new SearchFilter("stockInOut", SearchFilter.Operator.EQ,1));
            page.setFilters(filters);
        }
        Specification<FruitStockOrderInfo> specification = DynamicSpecifications.bySearchFilter(
                page.getFilters(), fruitStockOrderRepository.getDataClass());
        org.springframework.data.domain.Page<FruitStockOrderInfo> pageResult = fruitStockOrderRepository.findAll(specification, pageable);
        List<FruitStockOrderInfo> fruitStockOrderInfos = pageResult.getContent();
        List<FruitStockInfoDto> fruitStockInfoDtoList = new ArrayList<>();
        for(FruitStockOrderInfo fruitStockOrderInfo : fruitStockOrderInfos){
            FruitStockInfoDto fruitStockInfoDto = new FruitStockInfoDto();
            fruitStockInfoDto.setFruitStockId(fruitStockOrderInfo.getId());
            String fruitTypeName = typeRepository.getOne(fruitStockOrderInfo.getFruitTypeId()).getFruitTypeName();
            fruitStockInfoDto.setFruitName(fruitTypeName);
            Optional<User> user = userRepository.findById(fruitStockOrderInfo.getUserId());
            fruitStockInfoDto.setUserName(user.get().getAccount());
            fruitStockInfoDto.setFruitNumber(fruitStockOrderInfo.getStockOrderNumber());
            fruitStockInfoDto.setStockStatus(fruitStockOrderInfo.getStockOrderStatus());
            fruitStockInfoDtoList.add(fruitStockInfoDto);
        }
        pageRes.setTotal(Integer.valueOf(pageResult.getTotalElements() + ""));
        pageRes.setRecords(fruitStockInfoDtoList);
        return pageRes;
    }

    public Object stockOutAccept(Long fruitStockOrderId) {

        FruitStockOrderInfo fruitStockOrderInfo = this.get(fruitStockOrderId);
        fruitStockOrderInfo.setStockOrderStatus(FruitStockOutStatusEnum.ACCEPTED.getCode());
        FruitStockInfo fruitStockInfo = fruitStockRepository.findFruitStockInfoByFruitTypeIdAndAndUserId(
                fruitStockOrderInfo.getFruitTypeId(),fruitStockOrderInfo.getUserId());
        double newStockNumber = BigDecimalUtils.sub(fruitStockInfo.getFruitStockNumber(),fruitStockOrderInfo.getStockOrderNumber()).doubleValue();
        fruitStockInfo.setFruitStockNumber(newStockNumber);
        if(newStockNumber < 0){
            return Rets.failure("库存不足，无法出库");
        }
        //更新出库订单状态为 1
        this.update(fruitStockOrderInfo);
        //减少库存
        fruitStockRepository.save(fruitStockInfo);
        return Rets.success();
    }

    public List<FruitStockOrderInfoDto> listStockOrder(Long userId) {
        List<FruitStockOrderInfo> fruitStockOrderInfoList = fruitStockOrderRepository.findByUserIdAndStockInOut(userId,1);
        List<FruitStockOrderInfoDto> fruitStockOrderInfoDtoList = new ArrayList<>();
        for(FruitStockOrderInfo fruitStockOrderInfo : fruitStockOrderInfoList){
            FruitStockOrderInfoDto fruitStockOrderInfoDto = new FruitStockOrderInfoDto();
            String fruitTypeName = typeRepository.getOne(fruitStockOrderInfo.getFruitTypeId()).getFruitTypeName();
            Optional<User> user = userRepository.findById(fruitStockOrderInfo.getUserId());
            fruitStockOrderInfoDto.setUserName(user.get().getAccount());
            fruitStockOrderInfoDto.setStockOrderNumber(fruitStockOrderInfo.getStockOrderNumber());
            fruitStockOrderInfoDto.setStokcInOutStr(
                    fruitStockOrderInfo.getStockInOut() == 1?"出库":"入库");
            fruitStockOrderInfoDto.setFruitType(fruitTypeName + "-"+fruitStockOrderInfoDto.getStokcInOutStr());
            fruitStockOrderInfoDto.setStockInOutTime(fruitStockOrderInfo.getStockOrderTime());
            fruitStockOrderInfoDto.setStockOrderStatus(fruitStockOrderInfo.getStockOrderStatus());
            fruitStockOrderInfoDtoList.add(fruitStockOrderInfoDto);
        }
        return fruitStockOrderInfoDtoList;
    }
}
